﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AutoMapper;
using Tracker.Data.EFDAL;
using Tracker.Data.DataTransfer;
using Tracker.Data.EFDAL.Interfaces;

namespace Tracker.Services
{
    public class TaskData : ITaskData 
    {
        private DataEntities _cont;

        
        public TaskData(DataEntities context)
        {
            _cont = context;
        }

        public List<StatusDomain> GetStatusDomainList()
        {
            return _cont.StatusDomain.OrderBy(s => s.ID)
                .Select(Mapper.Map<Tracker.Data.EFDAL.Entity.StatusDomain, StatusDomain>).ToList();

        }

        public List<Task> GetTasks(DateTime datelimit, int statusid,string searchWord)
        {
            var la = _cont.Task.Include("Status_taskStatusDomain")
                .Where(t => (t.StatusId == statusid || statusid == 0)
                            && (t.CreatedDate >= datelimit)
                            && ( string.IsNullOrEmpty(searchWord) 
                                || t.Description.Contains(searchWord) 
                                ||t.Task_logLogList.Any(l=>l.Description.Contains(searchWord)))
                )
                .Select(Mapper.Map<Tracker.Data.EFDAL.Entity.Task, Task>)
                .ToList();
            return la;
        }
        public List<Task> GetTaskInfoList()
        {
            var lt = _cont.Task.Include("Status_taskStatusDomain")
                .Include("Task_logLogList")
                .Select(Mapper.Map<Tracker.Data.EFDAL.Entity.Task, Task>)
                .ToList();
            return lt;

        }
        public List<Task> GetTaskInfoList(DateTime createStart, DateTime createEnd, DateTime updateStart, DateTime updateEnd)
        {
            var lt = _cont.Task.Include("Status_taskStatusDomain")
                .Include("Task_logLogList")
                .Where(l => l.CreatedDate.Value >= createStart
                    && l.CreatedDate <= createEnd
                    && l.Task_logLogList.Max(lo => lo.ModifiedDate.Value) >= updateStart
                    && l.Task_logLogList.Max(loo => loo.ModifiedDate.Value) <= updateEnd
                    )
                .Select(Mapper.Map<Tracker.Data.EFDAL.Entity.Task, Task>)
                .ToList();
            return lt;

        }
        public List<Log> GetLog(int taskid)
        {
            return _cont.Log.Include("Status_LogStatusDomain").Include("Task_logTask")
                .Where(l => l.Task_logTask.ID == taskid)
                .Select(Mapper.Map<Tracker.Data.EFDAL.Entity.Log, Log>)
                .ToList();
        }

        public List<Log> GetLogInfoList()
        {
            var r = _cont.Log.Include("Status_LogStatusDomain").Include("Task_logTask")

                .Select(Mapper.Map<Tracker.Data.EFDAL.Entity.Log, Log>)
                .OrderBy(l => l.TaskId)
                .ThenBy(l => l.ID)

                .ToList();

            return r;
        }
        public List<Log> GetLogInfoList(DateTime createStart, DateTime createEnd, DateTime updateStart, DateTime updateEnd, string word)
        {
            var r = _cont.Log.Include("Status_LogStatusDomain").Include("Task_logTask")
                 .Where(lo =>
                    lo.Task_logTask.CreatedDate.Value >= createStart
                    && lo.Task_logTask.CreatedDate.Value <= createEnd
                    && lo.ModifiedDate >= updateStart
                    && lo.ModifiedDate <= updateEnd
                    && (string.IsNullOrEmpty(word) || (lo.Description.Contains(word)
                                                        || lo.Task_logTask.Description.Contains(word)
                        //|| lo.Task_logTask. need to add search in 
                        //dynamic properties
                                                        )
                        )
                    )
                .Select(Mapper.Map<Tracker.Data.EFDAL.Entity.Log, Log>)
                .OrderBy(l => l.TaskId)
                .ThenBy(l => l.ID)

                .ToList();

            return r;
        }

        public List<ObjectData> GetTaskField(int taskid)
        {
            return _cont.ObjectData.Include("ObjectAttribute").Where(t => t.Key == taskid
                && t.ObjectAttribute != null)
                .Select(Mapper.Map<Tracker.Data.EFDAL.Entity.ObjectData, ObjectData>).ToList();

        }

        public List<ObjectAttribute> GetTaskField()
        {
            return _cont.ObjectAttribute.Where(o => o.ObjectName == "task")
                .Select(Mapper.Map<Tracker.Data.EFDAL.Entity.ObjectAttribute, ObjectAttribute>).ToList();

        }


        public void AddTask(string detail, decimal hours)
        {
            var st = _cont.StatusDomain
                .Where(s => s.Status == "created")
                .FirstOrDefault();
            var t = new Tracker.Data.EFDAL.Entity.Task()
            {
                Description = detail,
                StatusId = st.ID
            };
            _cont.AddItem(t);
            _cont.SaveChanges();

            var l = new Tracker.Data.EFDAL.Entity.Log()
            {
                Description = detail,
                TaskId = t.ID,
                StatusId = st.ID,
                Hours = hours,
                UpdateTime = DateTime.Now
            };
            _cont.AddItem(l);
            _cont.SaveChanges();
        }


        public Task UpdateTask(Task task)
        {

            Tracker.Data.EFDAL.Entity.Task t = null;
            if (task.ID == 0)
            {
                t = new Tracker.Data.EFDAL.Entity.Task()
                {
                    Description = task.Description,
                    StatusId = task.StatusId
                };
                _cont.AddItem(t);
                _cont.SaveChanges();

                foreach (var item in GetTaskField())
                {
                    var f1 = task.Get<dynamic>(item.AttributeName);
                    UpdateTaskField(new ObjectData()
                    {
                        Key = task.ID,
                        AttributeId = item.ID,
                        Value = f1
                    });
                }

                //Add new log
                _cont.AddItem(new Tracker.Data.EFDAL.Entity.Log() { Description = "created", TaskId = t.ID, StatusId = t.StatusId });
                _cont.SaveChanges();

            }
            else
            {
                t = _cont.Task.Where(t1 => t1.ID == task.ID).FirstOrDefault();
                if (t != null)
                {
                    t.Description = task.Description;
                    t.StatusId = task.StatusId;
                    _cont.SaveChanges();


                    foreach (var item in GetTaskField())
                    {
                        var f1 = task.Get<dynamic>(item.AttributeName);
                        UpdateTaskField(new ObjectData()
                        {
                            Key = task.ID,
                            AttributeId = item.ID,
                            Value = f1
                        });
                    }
                }
            }
            return Mapper.Map<Tracker.Data.EFDAL.Entity.Task, Task>(t);
        }





        public void AddLog(int taskid, string detail, int statusid, decimal hours)
        {
            var t = _cont.Task.Where(tt => tt.ID == taskid).FirstOrDefault();
            t.StatusId = statusid;

            var l = new Tracker.Data.EFDAL.Entity.Log()
            {
                Description = detail,
                TaskId = taskid,
                StatusId = statusid,
                Hours = hours,
                UpdateTime = DateTime.Now
            };
            _cont.AddItem(l);
            _cont.SaveChanges();
        }

        public Log UpdateLog(Log log)
        {
            Tracker.Data.EFDAL.Entity.Log l = null;
            if (log != null)
            {
                var t = _cont.Task.Where(tt => tt.ID == log.TaskId).FirstOrDefault();
                t.StatusId = log.StatusId.HasValue ? log.StatusId.Value : 1;
                _cont.SaveChanges();

                if (log.ID == 0)
                {
                    l = new Tracker.Data.EFDAL.Entity.Log()
                    {
                        Description = log.Description,
                        StatusId = log.StatusId,
                        TaskId = log.TaskId,
                        Hours = log.Hours
                    };
                    _cont.AddItem(l);
                    _cont.SaveChanges();
                }
                else
                {
                    l = _cont.Log.Where(l1 => l1.ID == log.ID).FirstOrDefault();
                    if (l != null)
                    {
                        l.Description = log.Description;
                        l.StatusId = log.StatusId;
                        l.Hours = log.Hours;
                        _cont.SaveChanges();
                    }
                }
            }

            return Mapper.Map<Tracker.Data.EFDAL.Entity.Log, Log>(l);
        }

        public void DeleteLog(int logid)
        {
            var l = _cont.Log.Where(ll => ll.ID == logid).FirstOrDefault();
            if (l != null)
            {
                _cont.DeleteItem(l);
                _cont.SaveChanges();
            }
        }
        public void DeleteTask(int taskid)
        {
            var t = _cont.Task.Where(tt => tt.ID == taskid).FirstOrDefault();
            if (t != null)
            {
                foreach (var l in t.Task_logLogList.ToList())
                {
                    _cont.DeleteItem(l);
                    _cont.SaveChanges();

                }
                _cont.DeleteItem(t);
                _cont.SaveChanges();
            }
        }

        public void UpdateTaskField(ObjectData f)
        {
            var tf = _cont.ObjectData
                .Where(o => o.Key == f.Key && o.AttributeId == f.AttributeId).FirstOrDefault();
            if (tf != null)
            {
                tf.Value = f.Value;
                _cont.SaveChanges();
            }
            else
            {
                var t = new Tracker.Data.EFDAL.Entity.ObjectData() { Key = f.Key, AttributeId = f.AttributeId, Value = f.Value };
                _cont.AddItem(t);
                _cont.SaveChanges();
            }

        }

        public ObjectAttribute UpdateTaskFieldDomain(ObjectAttribute o)
        {

            var tf = _cont.ObjectAttribute
                  .Where(oo => oo.ID == o.ID).FirstOrDefault();
            if (tf != null)
            {
                tf.AttributeName = o.AttributeName;
                tf.AttributeType = "";
                tf.ObjectName = o.ObjectName;
                _cont.SaveChanges();
            }
            else
            {
                tf = new Tracker.Data.EFDAL.Entity.ObjectAttribute()
                {
                    AttributeName = o.AttributeName,
                    ObjectName = o.ObjectName,
                    AttributeType = ""
                };
                _cont.AddItem(tf);
                _cont.SaveChanges();
            }
            return Mapper.Map<Tracker.Data.EFDAL.Entity.ObjectAttribute, ObjectAttribute>(tf);
        }

        public StatusDomain UpdateStatusDomain(StatusDomain o)
        {

            var tf = _cont.StatusDomain
                  .Where(oo => oo.ID == o.ID).FirstOrDefault();
            if (tf != null)
            {
                tf.Status = o.Status;
                _cont.SaveChanges();
            }
            else
            {
                tf = new Tracker.Data.EFDAL.Entity.StatusDomain()
                {
                    Status = o.Status,
                };
                _cont.AddItem(tf);
                _cont.SaveChanges();
            }
            return Mapper.Map<Tracker.Data.EFDAL.Entity.StatusDomain, StatusDomain>(tf);
        }


        public void DeleteTaskFieldDomain(ObjectAttribute oa)
        {
            var o = _cont.ObjectAttribute.Where(o1 => o1.ID == oa.ID).FirstOrDefault();
            if (o != null)
            {

                _cont.ObjectAttribute.DeleteObject(o);
                _cont.SaveChanges();
            }
        }

        public void DeleteStatusDomain(StatusDomain sd)
        {
            var o = _cont.StatusDomain.Where(o1 => o1.ID == sd.ID).FirstOrDefault();
            if (o != null)
            {

                _cont.StatusDomain.DeleteObject(o);
                _cont.SaveChanges();
            }
        }

    }
}
